﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Narwhunderful.Aphelia.Framework.Graphics
{

    public class SpriteComponent : BasicSpriteComponent, ISpriteComponent
    {

        public SpriteComponent(Game game)
            : base(game)
        {
        }

        #region IUpdatableComponent

        protected override void InternalUpdate(GameTime gameTime)
        {
            UpdateOrigin(gameTime);
            UpdateTransform(gameTime);
            base.InternalUpdate(gameTime);        
        }

        protected internal override void UpdateRenderLocation(GameTime gameTime)
        {
            base.UpdateRenderLocation(gameTime);
            base.RenderLocation += _origin;
        }

        protected internal override void UpdateBounds(GameTime gameTime)
        {
            base.UpdateBounds(gameTime);
            _transformedBounds = DrawingHelper.GetTransformedRectangle(_transform, new Rectangle(0, 0, base.Bounds.Width, base.Bounds.Height));
            _transformedBounds.X += (int)_origin.X;
            _transformedBounds.Y += (int)_origin.Y;
        }

        protected internal void UpdateOrigin(GameTime gameTime)
        {
            _origin = new Vector2(base.SourceRectangle.Width / 2, base.SourceRectangle.Height / 2);
        }

        protected internal virtual void UpdateTransform(GameTime gameTime)
        {
            _transform =
                Matrix.CreateTranslation(new Vector3(-_origin, 0.0f)) *
                Matrix.CreateScale(_scale) *
                Matrix.CreateRotationZ(_rotation) *
                Matrix.CreateTranslation(new Vector3(base.Location, 0.0f));
        }

        #endregion

        #region IDrawableComponent

        protected override void InternalDrawTexture(GameTime gameTime)
        {
            base.SpriteBatch.Draw(base.TextureInformation.Texture, base.RenderLocation, base.SourceRectangle, base.TintColor, _rotation, _origin, _scale, _spriteEffects, 0);
        }

        #endregion

        #region ISpriteComponent

        Rectangle _transformedBounds = Rectangle.Empty;
        public Rectangle TransformedBounds
        {
            get
            {
                return _transformedBounds;
            }
            protected set
            {
                _transformedBounds = value;
            }
        }

        float _rotation = 0f;
        public float Rotation
        {
            get
            {
                return _rotation;
            }
            set
            {
                if (_rotation != value)
                {
                    _rotation = value;
                    base.NeedsUpdate = true;
                }
            }
        }

        float _scale = 1f;
        public float Scale
        {
            get
            {
                return _scale;
            }
            set
            {
                if (_scale != value)
                {
                    _scale = value;
                    base.NeedsUpdate = true;
                }
            }
        }

        Matrix _transform;
        public Matrix Transform
        {
            get
            {
                return _transform;
            }
            protected set
            {
                _transform = value;
            }
        }

        Vector2 _origin = Vector2.Zero;
        public Vector2 Origin
        {
            get
            {
                return _origin;
            }
            protected set
            {
                _origin = value;
            }
        }

        SpriteEffects _spriteEffects = SpriteEffects.None;
        public SpriteEffects SpriteEffects
        {
            get
            {
                return _spriteEffects;
            }
            set
            {
                _spriteEffects = value;
            }
        }

        public bool IntersectsTransformedBounds(Rectangle rectangle)
        {
            return _transformedBounds.Intersects(rectangle);
        }

        public bool IntersectsTransformedBounds(ISpriteComponent component)
        {
            return _transformedBounds.Intersects(component.TransformedBounds);
        }

        public bool IntersectsTransformedPixels(ISpriteComponent component)
        {
            if (!IntersectsTransformedBounds(component)) return false;
            return DrawingHelper.PixelsTransformedIntersect(_transform, base.TextureInformation.CacheRectangle, base.TextureInformation.PixelsCache, component.Transform, component.TextureInformation.CacheRectangle, component.TextureInformation.PixelsCache);
        }

        #endregion

    }

}
